﻿using LJ.Abstractions.DependencyInjection;
using LJ.Abstractions.Reflection;
using LJ.EventBus.Abstractions.Attributes;
using LJ.EventBus.Abstractions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using LJ.Abstractions.Extensions;
using Microsoft.Extensions.DependencyInjection;

namespace LJ.EventBus.HornedSerpent.Internal;

public class EventBusHandlerManager : IEventBusHandlerManager
{
    private readonly ConcurrentDictionary<string, EventBusHandlerDescriptor> _eventBusHandlerDescriptors = [];

    private readonly IDependencyManager _dependencyManager;

    private readonly IReflectionManager _reflectionManager;
    public EventBusHandlerManager(IDependencyManager dependencyManager, IReflectionManager reflectionManager)
    {
        _dependencyManager = dependencyManager;
        _reflectionManager = reflectionManager;


        //查找所有自动注册的服务实现类型进行注册
        var types = FindTypes();
        foreach (Type type in types)
        {
            var eventBusSubscribeAttribute = type.GetCustomAttribute<EventBusPublisherAttribute>();
            if (eventBusSubscribeAttribute != null)
            {
                _dependencyManager.ServiceCollection.AddTransient(type);
                var eventType = GetDataType(type);
                _eventBusHandlerDescriptors.AddOrUpdate(eventBusSubscribeAttribute.Topic,
                    a => new EventBusHandlerDescriptor(eventBusSubscribeAttribute.Topic, eventBusSubscribeAttribute.Group, eventType, type),
                    (a, b) => new EventBusHandlerDescriptor(eventBusSubscribeAttribute.Topic, eventBusSubscribeAttribute.Group, eventType, type));
            }

        }
    }

    public IReadOnlyCollection<EventBusHandlerDescriptor> GetEventBusHandlerDescriptors()
    {
        return [.. _eventBusHandlerDescriptors.Values];
    }

    public EventBusHandlerDescriptor GetEventBusHandlerDescriptor(string topicName)
    {
        if (_eventBusHandlerDescriptors.TryGetValue(topicName, out var handlerDescriptor))
        {
            return handlerDescriptor;
        }
        throw new ArgumentException($"[EventHandlerDescriptor] not : {topicName}");
    }

    private List<Type> FindTypes()
    {
        Type[] baseTypes = [typeof(IEventBusHandler<>)];
        return _reflectionManager.GetTypes(type => baseTypes.Any(b => type.IsDeriveClassFrom(b)) && type.HasAttribute<EventBusPublisherAttribute>());
    }

    private static Type GetDataType(Type type)
    {
        return type.GetTypeInfo()
            .ImplementedInterfaces
            .Single(r => r.IsGenericType && r.GetGenericTypeDefinition() == typeof(IEventBusHandler<>))
            .GetGenericArguments()
            .Single();
    }


}
